home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / presto / presto10.lha / src / process.h < prev    next >
C/C++ Source or Header  |  1991-12-11  |  8KB  |  294 lines

  1. #ifndef __presto__process_h__
  2. #define __presto__process_h__
  3.  
  4. //
  5. //
  6. //    Processes work as hungry puppies, banging on the scheduler
  7. //    until a ready job is available or until someone bangs on the
  8. //    process asking it to do something "out of band" (like pausing
  9. //    or dying).
  10. //
  11. // Modification History:
  12. //
  13. //   05-Dec-89  John Faust
  14. //   Remove stack free list.  Allocate stacks of fixed size when thread
  15. //   is allocated.  Stack remains associated with owning thread.  More
  16. //   efficient (removes search of stack freelist for stack of proper size,
  17. //   allocation of stack if one of proper size not found, and eliminates
  18. //   need to balance local stack freelists).
  19. //
  20. //   08-Nov-1989  John Faust
  21. //   Implement per-processor free lists of thread templates.
  22. //
  23.  
  24. extern Process *sysproc;
  25.  
  26. class Invocation;
  27.  
  28. //
  29. // Default maximum size of global thread freelist, threshhold of local list,
  30. // and number of threads to preallocate for local freelists.
  31. // Note that currently, thread size is 132 bytes.
  32. //
  33. // Using these values, the Create1M benchmark never has to allocate any threads
  34. // once the processes have been initialized.
  35. //
  36. #define GBL_THREAD_FREELIST_MAX    128
  37. #define LCL_THREAD_FREELIST_THRESH   8
  38. #define NUM_PREALLOC_THREADS         4
  39.  
  40. extern shared_t int gbl_thread_freelist_max;
  41. extern shared_t int lcl_thread_freelist_thresh;
  42.  
  43. class Process    : public Object     {
  44. #if (sun && THREAD_HAS_INTERRUPTIBLE_FIELD)
  45.     int    p_interruptible;
  46. #endif
  47. #ifdef vax
  48.     // WARNING: The offset of p_interruptible is known to swtch().
  49.     int    p_interruptible;
  50. #endif /* vax */
  51. #ifdef mips
  52.     // CAVEAT: swtch() for mips doesn't use this
  53.     int p_interruptible;
  54. #endif
  55.     char    *p_name;            // my name
  56.     int    p_id;                // my id
  57.     // WARNING: The offset of p_pid is known in hc_slock_asm.h
  58.     int    p_pid;                // system pid
  59.     int    p_ppid;                // system ppid
  60.         //
  61.         // Get and free threads from global shared thread freelist.
  62.         // Processes go to the list only when their local freelist becomes
  63.         // empty or when it gets to full.
  64.         //
  65.         void    get_gbl_threads ();
  66.         void    free_gbl_threads ();
  67.  
  68. protected:
  69.     int    p_state;            // whats up
  70.     int     p_flags;            // long term process stuff
  71.     int    p_request;            // stop spinning on this
  72.     Thread  *p_schedthread;            // where to swtch back to 
  73.     Thread    *p_thread;            // currently running thread
  74.         ThreadQUnlocked*    p_thread_freelist;  // per-processor thd freelist
  75. #define NEWPROCESS
  76.     virtual void    p_fork();               // take care of the fork
  77.     virtual void    p_wait();            // where we spin
  78.     virtual void    p_pause();            // internal ::pause
  79.     virtual void    p_runchild(int *spinflag);    // copy stack and go
  80. public:
  81.     Process(int ptag, int id);
  82.     Process();
  83.     Process(char* name, int id, int delayedfork = 0); // fork in ctor
  84.     virtual ~Process();
  85.     // virtual newprocess function.  After creation of the first thisproc,
  86.     // raw process constructor is not used.  thisproc->newprocess()  is
  87.     // used instead.  User can assign his own derivation of Process to
  88.     // thisproc in Main::init().
  89.     virtual Process* newprocess(char* name,int id);    
  90.  
  91.     // Processes, like threads, are not deallocated when destroyed
  92.     // The wisdom of this design is beyond me. PBD.
  93.  
  94.         void *operator new (size_t s) {
  95.         return ::operator new(s);
  96.     }
  97.         void operator delete(void *) {} // do not reclaim allocated space
  98.  
  99.     virtual int    request(int req);
  100.     virtual void    park();            // os pause
  101.     virtual void    drive();        // resume
  102.     virtual int    invoke();      
  103.         //
  104.         // Get and free threads from per-processor freelist.
  105.         //
  106.         inline Thread* get_thread (int* init_reqd);
  107.         inline void    free_thread (Thread* t);
  108.  
  109.     int    state()
  110.         { return p_state; }
  111.     void     setstate(int st)
  112.         { p_state = st; }
  113.     int     flags()
  114.         { return p_flags; }
  115.     inline int isroot();
  116.     int    id()                // scheduler id
  117.         {return p_id; }    
  118.     int    pid()            // unix id
  119.         { return p_pid; }
  120.     int     ppid()            // unix parent id
  121.         { return p_ppid; }
  122.     char *    name()
  123.         { return p_name; }
  124.     Thread    *schedthread()
  125.         { return p_schedthread; }
  126.     Thread    *runningthread()
  127.         { return p_thread; }
  128. #if (sun && THREAD_HAS_INTERRUPTIBLE_FIELD)
  129.     int    interruptible()
  130.         { return p_interruptible; }
  131.     inline int disable_interrupts();
  132.     void enable_interrupts()
  133.         { p_interruptible = 1; }
  134. #endif /* sun */
  135. #ifdef vax
  136.     int    interruptible()
  137.         { return p_interruptible; }
  138.     inline int disable_interrupts();
  139.     void enable_interrupts()
  140.         { p_interruptible = 1; }
  141. #endif /* vax */
  142. #ifdef mips
  143.     int    interruptible()
  144.         { return p_interruptible; }
  145.     inline int disable_interrupts();
  146.     void enable_interrupts()
  147.         { p_interruptible = 1; }
  148. #endif /* mips */
  149.     virtual void print(ostream& = cout);
  150.     virtual void    error(char *s);
  151. };
  152.  
  153.     
  154. #define R_NULL        0x00    /* nothing is happening */
  155. #define R_WAKEUP    0x01    /* wakeup wherever you are */
  156. #define R_PARK        0x02    /* put yourself to sleep in the OS */
  157. #define R_DIE        0x04    /* the nice way to kill a process */
  158. #define R_RETURN    0x08    /* relinquish control */
  159. /*
  160.  * We don't need R_DIE and R_RETURN since the process wait routine
  161.  * only understands how to R_RETURN from its scheduling loop.  Where
  162.  * it returns to is completely determined by how it was invoked.
  163.  * If it was invoked from runchild, then we will return to there
  164.  * and get nuked with a (delete this).  If we were called via runrun
  165.  * from the Main constructor, then we will return to single threaded
  166.  * control.
  167.  */
  168.  
  169. #define S_RUN        0x01    /* running */
  170. #define S_WAIT        0x02    /* unused.  waiting to be used in spinloop */
  171. #define S_SLEEP        0x04    /* sleeping on an event */
  172. #define S_OSPAUSE    0x08    /* WAITing or SLEEPing via OS pause */
  173. #define S_FREE        (S_WAIT|S_OSPAUSE)
  174. #define S_ZOMBIE    0x10
  175. #define S_EXITING    0x20
  176. #define S_DELAYEDFORK    0x40    /* constructed, but not yet forked */
  177. #define S_FORKING    0x80    /* as we speak... */
  178. #define S_ERROR        0x100
  179. #define S_REAPED    0x200    /* already cleaned up */
  180. #define S_REAPING    0x400    /* parent process cleaning up */
  181.  
  182.  
  183. //
  184. // special proc tags for flags field
  185. //
  186. #define P_ROOT        0x01
  187.  
  188. inline int Process::isroot()
  189. {
  190.     return (p_flags&P_ROOT);
  191. }
  192.  
  193. //
  194. //  Get a thread from the process freelist.  This is an unshared, unprotected
  195. //  queue, so access to it should be very fast.
  196. //
  197. inline Thread*
  198. Process::get_thread (int* init_reqd)
  199. {
  200.     Thread* t;
  201.  
  202.     // If called before Process context is established,
  203.     // just return a newly allocated Thread and say that
  204.     // it needs initializing
  205.  
  206.     if (this == 0)
  207.     {
  208.          *init_reqd = 1;
  209.      return (t = (Thread *) new char [sizeof(Thread)]);
  210.     }
  211.  
  212.     //
  213.     //  If this process' local freelist is exhausted, then try to grab some
  214.     //  more threads from the global queue.
  215.     //
  216.  
  217.     if (p_thread_freelist->length() == 0)
  218.         get_gbl_threads ();
  219.  
  220.     //
  221.     // Check local freelist for reuseable thread.  If none, allocate
  222.     // a new one.
  223.     //
  224.     t = p_thread_freelist->get ();
  225.     if (t)
  226.     {
  227.         *init_reqd = 0;
  228.         return t;
  229.     }
  230.     else
  231.     {
  232.         *init_reqd = 1;
  233.         return (t = (Thread*) new char [sizeof (Thread)]);
  234.     }
  235. }
  236.  
  237.  
  238. //
  239. //  Return a thread to the local freelist for this process.
  240. //
  241. inline void
  242. Process::free_thread (Thread* t)
  243. {
  244.     p_thread_freelist->append (t);
  245.     
  246.     //
  247.     //  If the local freelist is over threshhold, move half it's threads
  248.     //  to the global freelist.
  249.     //
  250.     if (p_thread_freelist->length() > lcl_thread_freelist_thresh)
  251.         free_gbl_threads ();
  252. }
  253.  
  254.  
  255. #if (sun && THREAD_HAS_INTERRUPTIBLE_FIELD)
  256. inline int Process::disable_interrupts()
  257. {
  258.     if (p_interruptible)    {
  259.         p_interruptible = 0;
  260.         return 1;
  261.  
  262.     } else
  263.         return 0;
  264. }
  265. #endif /* sun */
  266.  
  267. #ifdef vax
  268. inline int Process::disable_interrupts()
  269. {
  270.     if (p_interruptible)    {
  271.         p_interruptible = 0;
  272.         return 1;
  273.  
  274.     } else
  275.         return 0;
  276. }
  277. #endif /* vax */
  278.  
  279. #ifdef mips
  280. inline int Process::disable_interrupts()
  281. {
  282.     if (p_interruptible)    {
  283.         p_interruptible = 0;
  284.         return 1;
  285.  
  286.     } else
  287.         return 0;
  288. }
  289. #endif /* mips */
  290.  
  291. extern private_t Process    *thisproc;    // private to each proc
  292.  
  293. #endif /* __presto__process_h__ */
  294.